import os
import shutil
import pathlib
import logging
import secret

import netmiko
from functional import seq
from functools import wraps

from pathlib import Path, PurePosixPath

logger = logging.getLogger('my-deployer')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)


def d(NAME: str, COPY_PATH_RELATIVE: Path, copy_seq: []):
    def wrapper(f):
        @wraps(f)
        def wrapped(self, PROJECT_NAME: str):
            PY_NAME = 'my-script.py'
            LOCAL_PROJECT_PATH: Path = {
                'nodejs': self._nodejs_base_path.joinpath(PROJECT_NAME),
                'docker': self._docker_base_path.joinpath(PROJECT_NAME),
                'kotlin': self._kotlin_base_path.joinpath(PROJECT_NAME),
            }[NAME]
            REMOTE_PROJECT_BASE = self._remote_base_path.joinpath(NAME)
            COPY_PATH = LOCAL_PROJECT_PATH.joinpath(COPY_PATH_RELATIVE)
            if not COPY_PATH.exists():
                os.mkdir(COPY_PATH)
            if LOCAL_PROJECT_PATH.joinpath(PY_NAME).exists():
                copy_seq.append(PY_NAME)
            if len(copy_seq) > 0:
                seq(copy_seq).for_each(
                    lambda arg: shutil.copy(LOCAL_PROJECT_PATH.joinpath(arg), COPY_PATH))
            REMOTE_PROJECT_PATH = REMOTE_PROJECT_BASE.joinpath(PROJECT_NAME)
            self._send_command(f'rm -rf {REMOTE_PROJECT_PATH}')
            self._send_command(f'mkdir {REMOTE_PROJECT_PATH.parent} -p')
            self._system(
                f'scp -i {self.junos["key_file"]} -r {LOCAL_PROJECT_PATH.joinpath(COPY_PATH)} {self.junos["username"]}@{self.junos["host"]}:{REMOTE_PROJECT_BASE}/')
            self._send_command(f'mv {REMOTE_PROJECT_BASE.joinpath(COPY_PATH.name)} {REMOTE_PROJECT_PATH}')

            if LOCAL_PROJECT_PATH.joinpath(PY_NAME).exists():
                self._send_command(f'python3 {REMOTE_PROJECT_PATH.joinpath(PY_NAME)}')
            f(self, PROJECT_NAME)

        return wrapped

    return wrapper


class Deployer(object):
    def __init__(self, host_profile, debug: bool = False, print_result: bool = False):
        self.junos = host_profile
        self.print_result = print_result
        self.debug = debug
        if not debug:
            logger.debug('start connnect')
            self.ssh_conn = netmiko.ConnectHandler(**host_profile)
            logger.debug('connnect success')
        self._kotlin_base_path = Path(r'E:\Documents\IdeaProjects')
        self._docker_base_path = Path(r'E:\Documents\docker')
        self._nodejs_base_path = Path(r'E:\Documents\vscode')
        self._remote_base_path = PurePosixPath('~/autoshell')

    def _send_command(self, command: str, delay_factor: int = 1):
        if not self.debug:
            logger.debug(f'$$ {command}')
            res = self.ssh_conn.send_command(command, delay_factor=delay_factor)
            if self.print_result:
                print(res)
            return res
        return '测试'

    def _system(self, command: str):
        if not self.debug:
            logger.debug(f'$$$ {command}')
            os.system(command)
        return '测试'

    def docker_stop(self, PROJECT_NAME: Path):
        REMOTE_PROJECT_PATH = pathlib.PurePosixPath('~/autoshell/docker').joinpath(PROJECT_NAME)
        self._send_command(f'docker-compose -f {REMOTE_PROJECT_PATH.joinpath("docker-compose.yml")} down')

    @d('docker', Path(''), [])
    def build_docker_start(self, PROJECT_NAME: Path):
        REMOTE_PROJECT_PATH = self._remote_base_path.joinpath('docker').joinpath(PROJECT_NAME)
        self._send_command(f'docker-compose -f {REMOTE_PROJECT_PATH.joinpath("docker-compose.yml")} down')
        self._send_command(f'docker-compose -f {REMOTE_PROJECT_PATH.joinpath("docker-compose.yml")} up -d',
                           delay_factor=10)

    @d('nodejs', Path('build'), [])
    def build_nodejs(self, PROJECT_NAME: Path):
        pass

    @d('kotlin', Path('build/copy'), ['docker-compose.yml', 'Dockerfile', 'app.jar'])
    def build_kotlin(self, PROJECT_NAME: Path):
        pass


if __name__ == '__main__':
    Deployer(secret.pve, print_result=True).build_kotlin(Path('fpeg-kotlin\wordbase'))
